package hu.pixelesztergalyos.gui;

import hu.pixelesztergalyos.continuity.Character;
import hu.pixelesztergalyos.continuity.Gate;
import hu.pixelesztergalyos.continuity.Key;
import hu.pixelesztergalyos.continuity.Mosaic;
import hu.pixelesztergalyos.continuity.MosaicElement;
import hu.pixelesztergalyos.continuity.ViewState;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Panel;
import java.awt.Point;
import java.awt.geom.Point2D;
import java.awt.geom.Point2D.Float;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;

import org.omg.CORBA.portable.ApplicationException;

public class View {

  Character char1Ref;           // char1Ref: a remote reference to 1st character
  Character char2Ref;           // char2Ref: a remote reference to 2nd character
  Point currentMosaicCoord;     // currentMosaicCoord: active mosaic identification
  Gate gateRef;                 // gateRef: a remote reference to gate
  Key keyRef;                   // keyRef: a remote reference to key
  Mosaic[][] mosaicsRef;        // mosaicsRef: a remote reference to the loaded mosaics
  Controller c;                 // c: the controller object serving all of the referenced objects

	// GUI
  ImagePanel MMenupanel;         // MMenupanel: imagepanel for holding displayed mainmenu (ImagePanel extends JPanel)
  ImagePanel PMenupanel;         // PMenupanel: imagepanel for holding displayed pausemenu (ImagePanel extends JPanel)
  MosaicPanel mosPanel;          // mosPanel: imagepanel for holding the mosaics (MosaicPanel extends ImagePanel)

	// VIEWSTATE
	ViewState vs;
  public JFrame frame;             // frame: JFrame for holding all of the graphic elements
 
 public class ImagePanel extends JPanel {
    private Image image = null;            // image: for holding the background image
    public ImagePanel(String filename) {   // filename: image file
      this.image = new ImageIcon(filename).getImage(); // getImage: loading the image from filename
		}

		@Override
		protected void paintComponent(Graphics g) {
			super.paintComponent(g);
			g.drawImage(image, 0, 0, image.getWidth(null),
					image.getHeight(null), null);
		}
	}

	public class MosaicPanel extends JPanel {
   // images for later holding appropriate image files
		private Image char1Image = null;
		private Image char2Image = null;
		private Image keyImage = null;
		private Image gateImage = null;
		private Image gateImageTemp = null;
		private Image keyImageTemp = null;
		private Image char1_7x7Image = null;
		private Image char2_7x7Image = null;

    // MosaicPanel Constructor
    // Loading Image files
		public MosaicPanel() {
			this.char1Image = new ImageIcon(
					"src/hu/pixelesztergalyos/continuity/graphics/char1_15x15.png").getImage();
			this.char2Image = new ImageIcon(
					"src/hu/pixelesztergalyos/continuity/graphics/char2_15x15.png").getImage();
			this.char1_7x7Image = new ImageIcon(
					"src/hu/pixelesztergalyos/continuity/graphics/char1_7x7.png").getImage();
			this.char2_7x7Image = new ImageIcon(
					"src/hu/pixelesztergalyos/continuity/graphics/char2_7x7.png").getImage();
			this.gateImage = new ImageIcon(
					"src/hu/pixelesztergalyos/continuity/graphics/gate_26x30.png").getImage();
		}

		@Override
		protected void paintComponent(Graphics g) {
			super.paintComponent(g);
			if (vs == ViewState.MOSAIC) {
				Mosaic MosaicToDraw = mosaicsRef[currentMosaicCoord.x][currentMosaicCoord.y];
				for (int i = 0; i < MosaicToDraw.elements.size(); i++) {
					Point2D.Float p = (Float) MosaicToDraw.elements.get(i)
							.getOrigin().clone();
					p.x = p.x * 3;
					p.y = p.y * 3;
					g.setColor(Color.BLACK);
					g.fillRect((int) p.x, (int) p.y, 30, 30);
				}
				if (MosaicToDraw.getHasGate() == true) {
					Point2D.Float gateOrig = (Float) gateRef.getOrigin().clone();
					gateOrig.x = gateOrig.x * 3;
					gateOrig.y = gateOrig.y * 3;
					g.drawImage(gateImage, (int) gateOrig.x, (int) gateOrig.y, null);
				}
				if (MosaicToDraw.getHasKey() == true) {
					Point2D.Float keyOrig = (Float) keyRef.getOrigin().clone();
					keyOrig.x = keyOrig.x * 3;
					keyOrig.y = keyOrig.y * 3;
					
					if (char1Ref.getHasKey() || char2Ref.getHasKey()){
						this.keyImageTemp = new ImageIcon(
								"src/hu/pixelesztergalyos/continuity/graphics/key_szurke30x30.png").getImage();
					}else{	
						this.keyImageTemp = new ImageIcon(
							"src/hu/pixelesztergalyos/continuity/graphics/key_30x30.png").getImage();
					}
					
					g.drawImage(keyImageTemp, (int) keyOrig.x, (int) keyOrig.y,
							null);
				}
				if (MosaicToDraw.getHasCharacter() == true) {
					Point2D.Float char1Orig = (Float) char1Ref.getOrigin()
							.clone();
					char1Orig.x = char1Orig.x * 3;
					char1Orig.y = char1Orig.y * 3;
					g.drawImage(char1Image, (int) char1Orig.x, (int) char1Orig.y, null);
				}
				if (MosaicToDraw.getHasCharacter2() == true) {
					Point2D.Float char2Orig = (Float) char2Ref.getOrigin()
							.clone();
					char2Orig.x = char2Orig.x * 3;
					char2Orig.y = char2Orig.y * 3;
					g.drawImage(char2Image, (int) char2Orig.x, (int) char2Orig.y, null);
				}
			} else {
				int rows = mosaicsRef.length;
				int columns = mosaicsRef[0].length;
				for (int i = 0; i < rows; i++) {
					for (int j = 0; j < columns; j++) {
						// original_width_coordinates*((780/number_of_columns)/260)
						// + columnindex_of_mosaic*(780/number_of_columns)
						if (mosaicsRef[i][j] != null) {
							Mosaic MosaicToDrawTemp = mosaicsRef[i][j];
							for (int k = 0; k < MosaicToDrawTemp.elements.size(); k++) {
								Point2D.Float p2 = (Float) MosaicToDrawTemp.elements.get(k).getOrigin().clone();
								float newP2x = (p2.x * ((float) (780 / columns) / 260)) + (j * (780 / columns));
								float newP2y = (p2.y * (((float) (480 / rows) / 160))) + (i * ((480 / rows) - ((480 / rows) / 16)));
								if (p2.y == 0.0 || p2.x == 0.0 || p2.y == 140.0 || p2.x == 250.0) {
									g.setColor(Color.GRAY);
									g.fillRect((int) newP2x, (int) newP2y, 
											((780 / columns) / 26),
											((480 / rows) / 16));
								} else {
									g.setColor(Color.BLACK);
									g.fillRect((int) newP2x, (int) newP2y,
											((780 / columns) / 26),
											((480 / rows) / 16));
								}
							}
							if (MosaicToDrawTemp.getHasGate() == true) {
								Point2D.Float gateOrig = (Float) gateRef
										.getOrigin().clone();
								float newGateX = (gateOrig.x * ((float) (780 / columns) / 260))
										+ (j * (780 / columns));
								float newGateY = (gateOrig.y * (((float) (480 / rows) / 160)))
										+ (i * ((480 / rows) - ((480 / rows) / 16)));

								this.gateImageTemp = new ImageIcon(
										"src/hu/pixelesztergalyos/continuity/graphics/gate_"
												+ ((780 / columns) / 26) + "x"
												+ ((480 / rows) / 16) + ".png")
										.getImage();

								g.drawImage(gateImageTemp, (int) newGateX,
										(int) newGateY, null);
							}
							if (MosaicToDrawTemp.getHasKey() == true) {
								Point2D.Float keyOrig = (Float) keyRef
										.getOrigin().clone();
								float newKeyX = (keyOrig.x * ((float) (780 / columns) / 260))
										+ (j * (780 / columns));
								float newKeyY = (keyOrig.y * (((float) (480 / rows) / 160)))
										+ (i * ((480 / rows) - ((480 / rows) / 16)));
								if (char1Ref.getHasKey() || char2Ref.getHasKey()){
									this.keyImageTemp = new ImageIcon(
											"src/hu/pixelesztergalyos/continuity/graphics/key_szurke"
													+ ((780 / columns) / 26) + "x"
													+ ((480 / rows) / 16) + ".png")
											.getImage();
								}else{	
									this.keyImageTemp = new ImageIcon(
										"src/hu/pixelesztergalyos/continuity/graphics/key_"
												+ ((780 / columns) / 26) + "x"
												+ ((480 / rows) / 16) + ".png")
										.getImage();
								}
								g.drawImage(keyImageTemp, (int) newKeyX,
										(int) newKeyY, null);

							}
							if (MosaicToDrawTemp.getHasCharacter() == true) {

								Point2D.Float char1Orig = (Float) char1Ref
										.getOrigin().clone();
								float newChar1X = (char1Orig.x * ((float) (780 / columns) / 260))
										+ (j * (780 / columns));
								float newChar1Y = (char1Orig.y * (((float) (480 / rows) / 160)))
										+ (i * ((480 / rows) - ((480 / rows) / 16)));
								// itt shit van a kasztolassal
								// String charImageTemp((780 / columns) / 26);
								g.drawImage(char1_7x7Image, (int) newChar1X,
										(int) newChar1Y, null);
							}
							if (MosaicToDrawTemp.getHasCharacter2() == true) {
								Point2D.Float char2Orig = (Float) char2Ref
										.getOrigin().clone();
								float newChar2X = (char2Orig.x * ((float) (780 / columns) / 260))
										+ (j * (780 / columns));
								float newChar2Y = (char2Orig.y * (((float) (480 / rows) / 160)))
										+ (i * ((480 / rows) - ((480 / rows) / 16)));
								// itt shit van a kasztolassal
								g.drawImage(char2_7x7Image, (int) newChar2X,
										(int) newChar2Y, null);
							}

						}

					}
				}
			}
		}
	}

	// Constructor
	public View(Controller c) {
		this.c = c;

		// ==========================
		// INITIALIZING MAINMENU
		MMenupanel = new ImagePanel(
				"src/hu/pixelesztergalyos/continuity/graphics/maintitle.png");
		JButton btnNewGame = new JButton();

		JButton btnContinue = new JButton();
		JButton btnExit = new JButton();

		btnNewGame.addActionListener(c.handler);
		btnContinue.addActionListener(c.continueHandler);
		btnExit.addActionListener(c.exitHandler);
		btnNewGame.setIcon(new ImageIcon(
				"src/hu/pixelesztergalyos/continuity/graphics/mainnew.png"));
		btnContinue.setIcon(new ImageIcon(
				"src/hu/pixelesztergalyos/continuity/graphics/maincont.png"));
		btnExit.setIcon(new ImageIcon(
				"src/hu/pixelesztergalyos/continuity/graphics/mainexit.png"));

		btnNewGame.setContentAreaFilled(false);
		btnContinue.setContentAreaFilled(false);
		btnExit.setContentAreaFilled(false);
		
		btnNewGame.setBorderPainted(false);
		btnContinue.setBorderPainted(false);
		btnExit.setBorderPainted(false);

		MMenupanel.setLayout(new BoxLayout(MMenupanel, BoxLayout.Y_AXIS));
		MMenupanel.add(Box.createRigidArea(new Dimension(290, 320)));
		MMenupanel.add(btnNewGame);
		MMenupanel.add(btnContinue);
		MMenupanel.add(btnExit);
		MMenupanel.setVisible(false);
		// =========================

		// ==========================
		// INITIALIZING PAUSEMENU
		PMenupanel = new ImagePanel(
				"src/hu/pixelesztergalyos/continuity/graphics/pausetitle.png");
		JButton btnManiMenu = new JButton();

		JButton btnGoOn = new JButton();
		JButton btnExit_pm = new JButton();
		btnManiMenu.setIcon(new ImageIcon(
				"src/hu/pixelesztergalyos/continuity/graphics/pausemain.png"));
		btnGoOn.setIcon(new ImageIcon(
				"src/hu/pixelesztergalyos/continuity/graphics/pausecont.png"));
		btnExit_pm.setIcon(new ImageIcon(
				"src/hu/pixelesztergalyos/continuity/graphics/pauseexit.png"));

		
		btnManiMenu.addActionListener(c.mainMenuHandler);
		btnGoOn.addActionListener(c.goOnHandler);
		btnExit_pm.addActionListener(c.exitHandler);
		
		btnManiMenu.setContentAreaFilled(false);
		btnGoOn.setContentAreaFilled(false);
		btnExit_pm.setContentAreaFilled(false);

		btnManiMenu.setBorderPainted(false);
		btnGoOn.setBorderPainted(false);
		btnExit_pm.setBorderPainted(false);

		PMenupanel.setLayout(new BoxLayout(PMenupanel, BoxLayout.Y_AXIS));
		PMenupanel.add(Box.createRigidArea(new Dimension(290, 320)));
		PMenupanel.add(btnManiMenu);
		PMenupanel.add(btnGoOn);
		PMenupanel.add(btnExit_pm);
		PMenupanel.setVisible(false);

		mosPanel = new MosaicPanel();
		// ======================

		// ======================
		// CREATING WINDOW
		frame = new JFrame("PE - Continuity");
		frame.setSize(800, 600);
		frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		frame.getContentPane().add(MMenupanel, BorderLayout.CENTER);
		frame.setVisible(true);
		frame.setResizable(false);
		frame.createBufferStrategy(2);
  	renderMainMenu();

	}

	public void render() {
		mosPanel.repaint();
	}

	public void renderMainMenu() {
		PMenupanel.setVisible(false);
		MMenupanel.setVisible(true);
		mosPanel.setVisible(false);
		frame.getContentPane().add(MMenupanel, BorderLayout.CENTER);

	}

	public void renderPauseMenu() {
		PMenupanel.setVisible(true);
		MMenupanel.setVisible(false);
		mosPanel.setVisible(false);
		frame.getContentPane().add(PMenupanel, BorderLayout.CENTER);
	}

	public void setModelData(Character c1, Character c2, Gate g, Key k,
			Mosaic[][] mosaics, Point p) {
		this.char1Ref = c1;
		this.char2Ref = c2;
		this.gateRef = g;
		this.keyRef = k;
		this.mosaicsRef = mosaics;
		this.currentMosaicCoord = p;
	}
}
